package com.zhongjh.imageingstudy.view.image;

import android.animation.Animator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.FrameLayout;

import androidx.annotation.ColorInt;

import com.zhongjh.imageingstudy.anim.ImageHomingAnimator;
import com.zhongjh.imageingstudy.core.ImageMode;
import com.zhongjh.imageingstudy.homing.ImageHoming;
import com.zhongjh.imageingstudy.view.image.help.MoveAdapter;

/**
 * 裁剪
 */
public class ActionImageView extends FrameLayout {

    private final String TAG = ActionImageView.class.getSimpleName();
    private ImageMode mPreMode = ImageMode.NONE;

    public final ActionImage mActionImage = new ActionImage();
    /**
     * 手势监听类,主要是用于实现拖拽裁剪框
     */
    private GestureDetector mGestureDetector;

    private ImageHomingAnimator mHomingAnimator;

    /**
     * 一个延时活动，目前用于手势离开后纠正动画
     */
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "run");
            if (!onSteady()) {
                // 上面如果返回false,过了500毫秒再次触发自身事件
                postDelayed(this, 500);
            }
        }
    };

    public ActionImageView(Context context) {
        this(context, null, 0);
    }

    public ActionImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ActionImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        // 手势监听类
        mGestureDetector = new GestureDetector(context, new MoveAdapter(this));
    }

    /**
     * onLayout生命周期,决定了该view的大小
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        Log.d(TAG, "onLayout");
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            mActionImage.onLayout(right - left, bottom - top);
        }
    }

    /**
     * 重新在IMGView画图
     */
    @Override
    protected void onDraw(Canvas canvas) {
        onDrawImages(canvas);
    }

    /**
     * 处理触屏事件.详情
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
//        Log.d(TAG, "onTouchEvent");
        boolean handled = false;
        ImageMode mode = mActionImage.getMode();

        // 不做画线、花马赛克时,触屏该事件
        if (mode == ImageMode.NONE || mode == ImageMode.CLIP) {
            handled = onTouchNone(event);
        }

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mActionImage.onTouchDown(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // 触发归位
                postDelayed(runnable, 1200);
//                mActionImage.onTouchUp(getScrollX(), getScrollY());
//                invalidate();
                break;
            default:
                break;
        }
        return handled;
    }

    /**
     * 赋值图片资源
     */
    public void setImageBitmap(Bitmap image) {
        mActionImage.setBitmap(image);
        invalidate();
    }

    /**
     * 设置模式
     */
    public void setMode(ImageMode imageMode) {
        // 保存现在的编辑模式
        mPreMode = imageMode;
        // 设置新的编辑模式
        mActionImage.setMode(imageMode);
        onHoming();
    }

    /**
     * 绘制控件
     */
    private void onDrawImages(Canvas canvas) {
//        Log.d(TAG, "onDrawImages");
        canvas.save();

        // 绘制图片
        mActionImage.onDrawImage(canvas);

        // 绘制遮罩层,当裁剪框小于图片,这个交叉区域就是遮罩层
        mActionImage.onDrawShade(canvas);

        // 绘制裁剪框
        if (mActionImage.getMode() == ImageMode.CLIP) {
            canvas.save();
            canvas.translate(getScrollX(), getScrollY());
            mActionImage.onDrawClip(canvas, getScrollX(), getScrollY());
            canvas.restore();
        }
    }

    /**
     * 不做画线、花马赛克时,触屏该事件
     *
     * @param event 触屏
     */
    private boolean onTouchNone(MotionEvent event) {
//        Log.d(TAG, "onTouchNone");
        return mGestureDetector.onTouchEvent(event);
    }

    boolean onSteady() {
        Log.d(TAG, "onSteady: isHoming=" + isHoming());
        if (!isHoming()) {
            // 如果不是正在动画中,则开始归为动画,先设置相关参数
            mActionImage.setClipHomingFrame();
            onHoming();
            return true;
        }
        return false;
    }

    /**
     * 是否归位动画中
     */
    boolean isHoming() {
        Log.d(TAG, "isHoming");
        return mHomingAnimator != null
                && mHomingAnimator.isRunning();
    }

    /**
     * 归位动画中
     * 假设移动图片到某个区别或者放大缩小时，该方法用于变回原样
     */
    private void onHoming() {
        Log.d(TAG, "onHoming");
        stopHoming();
//        startHoming(mActionImage.getStartHoming(getScrollX(), getScrollY()),
//                mActionImage.getEndHoming(getScrollX(), getScrollY()));
        log();
        mActionImage.onHomingStart();
        log();
        ImageHoming applyHoming = evaluate(1, mActionImage.getStartHoming(getScrollX(), getScrollY()), mActionImage.getEndHoming(getScrollX(), getScrollY()));
        log();
        mActionImage.onHoming(1f);
        log();
        // 设置图片缩放\移动
        toApplyHoming(applyHoming);
        log();
        if (mActionImage.onHomingEnd(getScrollX(), getScrollY(), false)) {
            // 设置裁剪区域
            ImageHoming clipImageHoming = mActionImage.clip(getScrollX(), getScrollY());
//            log();
//            toApplyHoming(clipImageHoming);
//            log();
        }
    }

    private void log() {
//        Log.d(TAG, "frame     top:" + mActionImage.mFrame.top + " left:" + mActionImage.mFrame.left + " bottom:" + mActionImage.mFrame.bottom + " right:" + mActionImage.mFrame.right);
//        Log.d(TAG, "clipFrame top:" + mActionImage.mClipFrame.top + " left:" + mActionImage.mFrame.left + " bottom:" + mActionImage.mFrame.bottom + " right:" + mActionImage.mFrame.right);
        Log.d(TAG, "VFrame    top:" + mActionImage.mImageClipView.getFrame().top + " left:" + mActionImage.mImageClipView.getFrame().left + " bottom:" + mActionImage.mImageClipView.getFrame().bottom + " right:" + mActionImage.mImageClipView.getFrame().right);
//        Log.d(TAG, "VHFrame   top:" + mActionImage.mImageClipView.getHomingFrame().top + " left:" + mActionImage.mImageClipView.getHomingFrame().left + " bottom:" + mActionImage.mImageClipView.getHomingFrame().bottom + " right:" + mActionImage.mImageClipView.getHomingFrame().right);
    }

    public ImageHoming evaluate(float fraction, ImageHoming startValue, ImageHoming endValue) {
        float x = startValue.x + fraction * (endValue.x - startValue.x);
        float y = startValue.y + fraction * (endValue.y - startValue.y);
        float scale = startValue.scale + fraction * (endValue.scale - startValue.scale);
        float rotate = startValue.rotate + fraction * (endValue.rotate - startValue.rotate);
        return new ImageHoming(x, y, scale, rotate);
    }

    /**
     * 开始归位动画
     */
    private void startHoming(ImageHoming sHoming, ImageHoming eHoming) {
        Log.d(TAG, "startHoming");
        if (mHomingAnimator == null) {
            mHomingAnimator = new ImageHomingAnimator();
            mHomingAnimator.addUpdateListener(animation -> {
//                Log.d(TAG, "onAnimationUpdate");
                mActionImage.onHoming(animation.getAnimatedFraction());
                toApplyHoming((ImageHoming) animation.getAnimatedValue());
            });
            mHomingAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    Log.d(TAG, "onAnimationStart");
                    mActionImage.onHomingStart();
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    Log.d(TAG, "onAnimationEnd");
                    if (mActionImage.onHomingEnd(getScrollX(), getScrollY(), mHomingAnimator.isRotate())) {
                        toApplyHoming(mActionImage.clip(getScrollX(), getScrollY()));
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    Log.d(TAG, "onAnimationCancel");
                    mActionImage.onHomingCancel(mHomingAnimator.isRotate());
                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
        }
        mHomingAnimator.setHomingValues(sHoming, eHoming);
        mHomingAnimator.start();
    }

    /**
     * 停止归位动画
     */
    private void stopHoming() {
        Log.d(TAG, "stopHoming");
        if (mHomingAnimator != null) {
            mHomingAnimator.cancel();
        }
    }

    /**
     * 设置图片的倍率、角度、图片位置,以下三种场景用到
     * 1. 动画进行时
     * 2. 动画结束后
     * 3. 移动、拉伸图片后
     */
    private void toApplyHoming(ImageHoming homing) {
        Log.d(TAG, "toApplyHoming " +
                "homing.scale：" + homing.scale + " homing.rotate：" + homing.rotate + " homing.x：" + homing.x + " homing.y：" + homing.y);
        mActionImage.setScale(homing.scale);
        mActionImage.setRotate(homing.rotate);
        if (!onScrollTo(Math.round(homing.x), Math.round(homing.y))) {
            invalidate();
        }
    }

    /**
     * 移动自身
     */
    private boolean onScrollTo(int x, int y) {
//        Log.d(TAG, "onScrollTo x" + x + " y" + y);
        if (getScrollX() != x || getScrollY() != y) {
            scrollTo(x, y);
            return true;
        }
        return false;
    }

    /**
     * 完成裁剪
     */
    public void doClip() {
        Log.d(TAG, "doClip");
//        mActionImage.clip(getScrollX(), getScrollY());
//        setMode(mPreMode);
//        onHoming();
//        invalidate();
        jilu();
    }

    private void jilu() {
        mPreImageHoming = mActionImage.getStartHoming(getScrollX(), getScrollY());
        mImagePreWindow.set(mActionImage.mWindow);
        mImagePreFrame.set(mActionImage.mFrame);
        mImagePreClipFrame.set(mActionImage.mClipFrame);
        mClipPreWin.set(mActionImage.mImageClipView.mWin);
        mClipPreWinFrame.set(mActionImage.mImageClipView.getWinFrame());
        mClipPreFrame.set(mActionImage.mImageClipView.getFrame());
        mClipPreHomingFrame.set(mActionImage.mImageClipView.getHomingFrame());
    }

    ImageHoming mPreImageHoming;
    RectF mImagePreWindow = new RectF();
    RectF mImagePreFrame = new RectF();
    RectF mImagePreClipFrame = new RectF();
    RectF mClipPreWin = new RectF();
    RectF mClipPreWinFrame = new RectF();
    RectF mClipPreFrame = new RectF();
    RectF mClipPreHomingFrame = new RectF();

    /**
     * 撤销
     */
    public void doUndo() {
        mActionImage.mWindow.set(mImagePreWindow);
        mActionImage.mFrame.set(mImagePreFrame);
        mActionImage.mClipFrame.set(mImagePreClipFrame);
        mActionImage.mImageClipView.mWin.set(mClipPreWin);
        mActionImage.mImageClipView.getWinFrame().set(mClipPreWinFrame);
        mActionImage.mImageClipView.getFrame().set(mClipPreFrame);
        mActionImage.mImageClipView.getHomingFrame().set(mClipPreHomingFrame);
//        invalidate();

        stopHoming();
        startHoming(mActionImage.getStartHoming(getScrollX(), getScrollY()),mPreImageHoming);
//        mActionImage.onHomingStart();
//        ImageHoming applyHoming = evaluate(1, mActionImage.getStartHoming(getScrollX(), getScrollY()), mPreImageHoming);
//        mActionImage.onHoming(1f);
//        toApplyHoming(applyHoming);
//        if (mActionImage.onHomingEnd(getScrollX(), getScrollY(), false)) {
//            toApplyHoming(mActionImage.clip(getScrollX(), getScrollY()));
//        }
    }
}
